/**
 * 
 */
package due.pc.pcshoot.level;


import java.io.BufferedInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.xml.parsers.ParserConfigurationException;
import javax.xml.parsers.SAXParser;
import javax.xml.parsers.SAXParserFactory;

import org.anddev.andengine.engine.Engine;
import org.anddev.andengine.util.Debug;
import org.anddev.andengine.util.StreamUtils;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;
import org.xml.sax.XMLReader;

import android.content.Context;

/**
 * @author manhhung.vu
 *
 */
public class LevelLoader implements ILoader
{
	//===============================================================/
	//Constants
	//===============================================================/
	public static final String LEVEL_ASSET_BASEPATH = "level/";
		
	
	//===============================================================/
	//Fields
	//===============================================================/
	private final HashMap<String, ILoader> mEnemyLoaders = new HashMap<String, ILoader>();
	
	private Level mLevel;
	
	//===============================================================/
	//Constructors
	//===============================================================/
	public LevelLoader() {
		// TODO Auto-generated constructor stub
	}

	
	//===============================================================/
	//Inherited Methods		
	//===============================================================/
	public void onEntityLoaded(String pLocalName) {};
	
	@Override
	public void onLoadEntity(String pEntityName, Attributes pAttributes) 
	{
		String value = pAttributes.getValue(LoaderConstants.TAG_LEVEL_ATTRIBUTE_SHOTS);
		int shots = (value != null) ? Integer.parseInt(value) : 10; 
		
		mLevel = new Level(
				pAttributes.getValue(LoaderConstants.TAG_LEVEL_ATTRIBUTE_NAME), 
				shots);
	}
	
	
	//===============================================================/
	//Methods
	//===============================================================/
	
	
	
	public void registerEntityLoader(final String pEntityName, final ILoader peEnemyLoader) {
		mEnemyLoaders.put(pEntityName, peEnemyLoader);
	}

	public void registerEntityLoader(final String[] pEntityNames, final ILoader peEnemyLoader) 
	{
		for(int i = pEntityNames.length - 1; i >= 0; i--) {
			mEnemyLoaders.put(pEntityNames[i], peEnemyLoader);
		}
	}

	public void loadLevelFromAsset(final Context pContext, final String pAssetPath) throws IOException {
		this.loadLevelFromStream(pContext.getAssets().open(LEVEL_ASSET_BASEPATH + pAssetPath));
	}

	public void loadLevelFromStream(final InputStream pInputStream) throws IOException {
		try{
			final SAXParserFactory spf = SAXParserFactory.newInstance();
			final SAXParser sp = spf.newSAXParser();

			final XMLReader xr = sp.getXMLReader();

			final LevelParser levelParser = new LevelParser(mEnemyLoaders);
			xr.setContentHandler(levelParser);

			xr.parse(new InputSource(new BufferedInputStream(pInputStream)));

		} catch (final SAXException se) {
			Debug.e(se);
			/* Doesn't happen. */
		} catch (final ParserConfigurationException pe) {
			Debug.e(pe);
			/* Doesn't happen. */
		} finally {
			StreamUtils.close(pInputStream);
		}
	}
	
	
	
	//===============================================================/
	//Getters & Setters
	//===============================================================/
	
	
	//===============================================================/
	//Static Methods
	//===============================================================/
	public static Level loadLevel(String pLevelName, Engine pEngine, Context pContext)
	{
		LevelLoader levelLoader = new LevelLoader();
		EnemyLoader enemyLoader = new EnemyLoader(pEngine, pContext);
		
		levelLoader.registerEntityLoader(
				new String[]{
						LoaderConstants.TAG_ENEMY,
						LoaderConstants.TAG_MODIFIER,
				}, 
				enemyLoader);		
		levelLoader.registerEntityLoader(LoaderConstants.TAG_LEVEL, levelLoader);
		
		try {
			levelLoader.loadLevelFromAsset(pContext, pLevelName);
		} 
		catch (IOException e) {
			Debug.d(e.getMessage());
		}
		
		levelLoader.mLevel.setEnemies(enemyLoader.getEnemies());
		return levelLoader.mLevel;
	}
	
	
	
	//===============================================================/
	//Inner Classes
	//===============================================================/
}
